`timescale 1ns / 1ps

module stream_combine
#(
    parameter BIT   = 8,
    parameter N_IO  = 2,
    parameter N_CH0 = 768,
    parameter N_CH1 = 512
)
(
    input   clk,
    input   rst,

    input   i0_vld,
    output  i0_rdy,
    input   [N_IO*BIT-1 : 0]    i0_data,

    input   i1_vld,
    output  i1_rdy,
    input   [N_IO*BIT-1 : 0]    i1_data,

    output  o_vld,
    input   o_rdy,
    output  [N_IO*BIT-1 : 0]    o_data
);

localparam N = (N_CH0 + N_CH1) / N_IO;
localparam MID = N_CH0 / N_IO;

wire sel;
wire ena;
wire [$clog2(N)-1 : 0]   cnt;

wire i_rdy;
wire i_vld;

assign sel = cnt < MID;
assign ena = o_rdy & o_vld;

assign i0_rdy =  sel & o_rdy;
assign i1_rdy = ~sel & o_rdy;
assign o_vld  = sel ? i0_vld : i1_vld;
assign o_data = sel ? i0_data : i1_data;

zq_counter #(
    .N      ( N )
) inst_cnt
(
    .clk    (clk),
    .rst    (rst),
    .clken  (ena),
    .last   (),
    .out    (cnt)
);

endmodule


module stream_copy
#(
    parameter BIT   = 8,
    parameter N_IO  = 2
)
(
    input   clk,
    input   rst,

    input   i_vld,
    output  i_rdy,
    input   [N_IO*BIT-1 : 0]    i_data,

    output  o0_vld,
    input   o0_rdy,
    output  [N_IO*BIT-1 : 0]    o0_data,

    output  o1_vld,
    input   o1_rdy,
    output  [N_IO*BIT-1 : 0]    o1_data
);

assign i_rdy = o0_rdy & o1_rdy;
assign o0_vld = i_vld & i_rdy;
assign o1_vld = i_vld & i_rdy;
assign o0_data = i_data;
assign o1_data = i_data;

endmodule


module stream_addlast
#(
    parameter BIT   = 8,
    parameter N_IO  = 2,
    parameter N_CNT = 50 * 10
)
(
    input   clk,
    input   rst,

    input   i_vld,
    output  i_rdy,
    input   [N_IO*BIT-1 : 0]    i_data,

    output  o_vld,
    input   o_rdy,
    output  o_last,
    output  [N_IO*BIT-1 : 0]    o_data
);

localparam N = N_CNT / N_IO;

wire ena;
assign ena = i_vld & o_rdy;

assign i_rdy = o_rdy;
assign o_vld = i_vld;
assign o_data = i_data;

zq_counter #(
    .N      ( N )
) inst_cnt
(
    .clk    (clk),
    .rst    (rst),
    .clken  (ena),
    .last   (o_last),
    .out    ()
);

endmodule

